}
static GtkWidget *
-fire_bin_new (void)
+ripple_bin_new (void)
{
GtkWidget *bin = gtk_shader_bin_new ();
static GskGLShader *shader = NULL;
if (shader == NULL)
- shader = gsk_gl_shader_new_from_resource ("/gltransition/fire.glsl");
+ shader = gsk_gl_shader_new_from_resource ("/gltransition/ripple.glsl");
- gtk_shader_bin_add_shader (GTK_SHADER_BIN (bin), shader, GTK_STATE_FLAG_PRELIGHT, GTK_STATE_FLAG_PRELIGHT);
+ gtk_shader_bin_add_shader (GTK_SHADER_BIN (bin), shader, GTK_STATE_FLAG_PRELIGHT, GTK_STATE_FLAG_PRELIGHT, 20);
return bin;
}
static GtkWidget *
make_shader_stack (const char *name,
const char *resource_path,
+ int active_child,
GtkWidget *scale)
{
GtkWidget *stack, *child, *widget, *vbox, *hbox, *bin;
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
+ gtk_shader_stack_set_active (GTK_SHADER_STACK (stack), active_child);
+
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
widget = gtk_center_box_new ();
gtk_box_append (GTK_BOX (vbox), widget);
- gtk_box_append (GTK_BOX (vbox), stack);
+ GtkWidget *bin2 = ripple_bin_new ();
+ gtk_shader_bin_set_child (GTK_SHADER_BIN (bin2), stack);
+
+ gtk_box_append (GTK_BOX (vbox), bin2);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign (hbox, GTK_ALIGN_CENTER);
button = gtk_button_new_from_icon_name ("go-previous");
g_signal_connect (button, "clicked", G_CALLBACK (go_back), stack);
- bin = fire_bin_new ();
+ bin = ripple_bin_new ();
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
gtk_box_append (GTK_BOX (hbox), bin);
button = gtk_button_new_from_icon_name ("go-next");
g_signal_connect (button, "clicked", G_CALLBACK (go_forward), stack);
- bin = fire_bin_new ();
+ bin = ripple_bin_new ();
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
gtk_box_append (GTK_BOX (hbox), bin);
static GtkWidget *
create_gltransition_window (GtkWidget *do_widget)
{
- GtkWidget *window, *headerbar, *scale, *grid;
+ GtkWidget *window, *headerbar, *scale, *outer_grid, *grid, *background;
+ GdkPaintable *paintable;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
+ outer_grid = gtk_grid_new ();
+ gtk_window_set_child (GTK_WINDOW (window), outer_grid);
+
+ paintable = gsk_shader_paintable_new (gsk_gl_shader_new_from_resource ("/gltransition/fire.glsl"), NULL);
+ background = gtk_picture_new_for_paintable (paintable);
+ gtk_widget_add_tick_callback (background, update_paintable, NULL, NULL);
+
+ gtk_grid_attach (GTK_GRID (outer_grid),
+ background,
+ 0, 0, 1, 1);
+
grid = gtk_grid_new ();
- gtk_window_set_child (GTK_WINDOW (window), grid);
+ gtk_grid_attach (GTK_GRID (outer_grid),
+ grid,
+ 0, 0, 1, 1);
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
gtk_grid_attach (GTK_GRID (grid),
- make_shader_stack ("Wind", "/gltransition/transition1.glsl", scale),
+ make_shader_stack ("Wind", "/gltransition/transition1.glsl", 0, scale),
0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid),
- make_shader_stack ("Radial", "/gltransition/transition2.glsl", scale),
+ make_shader_stack ("Radial", "/gltransition/transition2.glsl", 1, scale),
1, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid),
- make_shader_stack ("Crosswarp", "/gltransition/transition3.glsl", scale),
+ make_shader_stack ("Crosswarp", "/gltransition/transition3.glsl", 2, scale),
0, 1, 1, 1);
gtk_grid_attach (GTK_GRID (grid),
- make_shader_stack ("Kaleidoscope", "/gltransition/transition4.glsl", scale),
+ make_shader_stack ("Kaleidoscope", "/gltransition/transition4.glsl", 3, scale),
1, 1, 1, 1);
return window;
GskGLShader *shader;
GtkStateFlags state;
GtkStateFlags state_mask;
+ float extra_border;
gboolean compiled;
gboolean compiled_ok;
} ShaderInfo;
GPtrArray *shaders;
guint tick_id;
float time;
+ float mouse_x, mouse_y;
gint64 first_frame_time;
};
return G_SOURCE_CONTINUE;
}
+static void
+motion_cb (GtkEventControllerMotion *controller,
+ double x,
+ double y,
+ GtkShaderBin *self)
+{
+ self->mouse_x = x;
+ self->mouse_y = y;
+}
+
static void
gtk_shader_bin_init (GtkShaderBin *self)
{
+ GtkEventController *controller;
self->shaders = g_ptr_array_new_with_free_func ((GDestroyNotify)shader_info_free);
+
+ controller = gtk_event_controller_motion_new ();
+ g_signal_connect (controller, "motion", G_CALLBACK (motion_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), controller);
}
void
gtk_shader_bin_add_shader (GtkShaderBin *self,
GskGLShader *shader,
GtkStateFlags state,
- GtkStateFlags state_mask)
+ GtkStateFlags state_mask,
+ float extra_border)
{
ShaderInfo *info = g_new0 (ShaderInfo, 1);
info->shader = g_object_ref (shader);
info->state = state;
info->state_mask = state_mask;
+ info->extra_border = extra_border;
g_ptr_array_add (self->shaders, info);
if (self->active_shader->compiled_ok)
{
+ float border = self->active_shader->extra_border;
+ graphene_vec2_t mouse;
+ graphene_vec2_init (&mouse, self->mouse_x + border, self->mouse_y + border);
gtk_snapshot_push_gl_shader (snapshot, self->active_shader->shader,
- &GRAPHENE_RECT_INIT(0, 0, width, height),
+ &GRAPHENE_RECT_INIT(-border, -border, width+2*border, height+2*border),
gsk_gl_shader_format_args (self->active_shader->shader,
"u_time", self->time,
+ "u_mouse", &mouse,
NULL));
gtk_widget_snapshot_child (widget, self->child, snapshot);
gtk_snapshot_gl_shader_pop_texture (snapshot);
--- /dev/null
+uniform float u_time;
+uniform vec2 u_mouse;
+uniform sampler2D u_texture1;
+
+#define PI 3.141592654
+
+float decay(float v, float t)
+{
+ return v * (1.0 / (1.0 + t*t));
+}
+
+void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
+{
+ // Temporary to loop time every 1 sec
+ float time = u_time;
+ // we normalize all the effects according to the min height/width
+ float size = min(resolution.x, resolution.y);
+
+ // Animate one wave over size in 0.3 sec
+ float wave_speed = size / 0.3;
+ float wave_length = size / 1.0;
+ float wave_height = size * 0.1;
+
+ vec2 center = u_mouse;
+ vec2 direction_from_center = fragCoord - center;
+ float distance_from_center = length(direction_from_center);
+
+ /* Normalize direction */
+ direction_from_center = direction_from_center / distance_from_center;
+
+ float propagation_length = time * wave_speed;
+
+ float t = (propagation_length - distance_from_center) / wave_length;
+ float offset_magnitude = 0;
+ if (t > 0.0)
+ offset_magnitude = decay(wave_height * sin(t * 2.0 * PI), t);
+
+ vec2 offset = direction_from_center * min(offset_magnitude, distance_from_center);
+ vec2 source = fragCoord - offset;
+
+ vec2 uv2 = source / resolution;
+ fragColor = GskTexture(u_texture1, vec2(uv2.x, 1.0-uv2.y));
+}